﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Reflection;
using System.Web;
using Corp.Library.PersistenceLayer;
using Corp.Library.PersistenceLayer.Enums;
using Corp.Library.PersistenceLayer.AttributeProfile;
using Corp.Library.DataFactory;
using Corp.Library.PersistenceLayer.Mapping;
using LC.Common.Enum;
using LC.Common.CustomAttributes;
using NPOI.HSSF.UserModel;
using System.IO;
namespace LC.Common.Extensions
{
    public static class ExtensionMethod
    {
        #region object 扩展方法
        public static string ToJson(this object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.Indented,
                    new JsonSerializerSettings
                    {
                        DateFormatString = "yyyy-MM-dd HH:mm:ss",
                        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                    }
                );
        }
        public static string ToJsonDate(this object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.Indented,
                    new JsonSerializerSettings
                    {
                        DateFormatString = "yyyy-MM-dd",
                        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                    }
                );
        }
        public static void WriteJson(this HttpResponse response, object jsonStr)
        {
            response.ContentType = "application/json";
            response.Write(jsonStr);
            response.End();
        }
        public static void WriteJson(this HttpResponse response, string jsonStr)
        {
            response.ContentType = "application/json";
            response.Write(jsonStr);
            response.End();
        }
        public static void OutputStream(this HttpResponse Response, HSSFWorkbook workbook, string fileName)
        {
            Response.Clear();
            Response.Buffer = true;
            Response.Charset = "utf-8";
            Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
            Response.ContentEncoding = System.Text.Encoding.Default;//设置输出流为简体中文
            Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。
            workbook.Write(Response.OutputStream);
            Response.Flush();
            Response.End();
        }
        public static void OutputExcel(this HttpResponse Response,MemoryStream ms, string fileName)
        {
            Encoding encoding;
            string outputFileName = string.Empty;
            string browser = HttpContext.Current.Request.UserAgent.ToUpper();
            if (browser.Contains("MS") == true && browser.Contains("IE") == true)
            {
                outputFileName = HttpUtility.UrlEncode(fileName);
                encoding = System.Text.Encoding.UTF8;
            }
            else if (browser.Contains("FIREFOX") == true)
            {
                outputFileName = HttpUtility.UrlDecode(fileName,Encoding.UTF8);
                encoding = System.Text.Encoding.UTF8;
            }
            else
            {
                outputFileName = fileName;
                encoding = System.Text.Encoding.UTF8;
            }
            Response.Clear();
            Response.Buffer = true;
            Response.AppendHeader("Content-Disposition", "attachment;filename=" + outputFileName);
            Response.ContentEncoding = encoding;//设置输出流为简体中文
            Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。
            ms.WriteTo(Response.OutputStream);
            Response.Flush();
            Response.End();
        }
        public static object Deserialize(this string str)
        {
            return (object)JsonConvert.DeserializeObject(str);
        }
        public static IEnumerable<TSource> FormJson<TSource>(this IEnumerable<TSource> source, string jsonStr)
        {
            return (List<TSource>)JsonConvert.DeserializeObject<IEnumerable<TSource>>(jsonStr);
        }
        #endregion
        #region  基类 Entity 方法扩展
        public static bool UpdateSave(this Entity model, object id)
        {
            List<object> _ids = new List<object>();
            _ids.Add(id);
            return DataAccess.Execute(model.EntityConvert.BuildUpdateCommand(_ids.ToArray()));
        }
       
        public static string GetUpdateSaveSql(this Entity model, object id)
        {
            List<object> _ids = new List<object>();
            _ids.Add(id);
            return model.EntityConvert.BuildUpdateCommand(_ids.ToArray());
        }
        //public static string GetSqlWhere(this Entity model)
        //{

        //}
        /// <summary>
        /// 自动得到查询sql
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static string GetSqlWhere(this Entity model)
        {
            Dictionary<int, string> SqlConditionEnumMap = new Dictionary<int, string>();
            SqlConditionEnumMap.Add(0, "like");
            SqlConditionEnumMap.Add(1, "=");
            SqlConditionEnumMap.Add(2, "<");
            SqlConditionEnumMap.Add(3, "<=");
            SqlConditionEnumMap.Add(4, ">");
            SqlConditionEnumMap.Add(5, ">=");
            SqlConditionEnumMap.Add(6, "in");
            var attrs = model.GetType().GetCustomAttributes(typeof(SqlConditionAttribute),true);
            StringBuilder sqlWhere = new StringBuilder();
            foreach (PropertyInfo info in model.GetType().GetProperties())
            {
                SqlConditionAttribute customAttribute = (SqlConditionAttribute)Attribute.GetCustomAttribute(info, typeof(SqlConditionAttribute));
                var propertyValue = model.GetType().GetProperty(info.Name).GetValue(model, null);
                if (customAttribute != null && IsEmpty(info.PropertyType,propertyValue))
                {
                    var value = FormartValue(customAttribute.Condition, info.PropertyType,propertyValue);
                    sqlWhere.AppendFormat(" and {0} {1} {2}",customAttribute.FieldName,SqlConditionEnumMap[(int)customAttribute.Condition],value);
                }
            }
            return sqlWhere.ToString();
        }
        public static bool IsEmpty(Type type,object value)
        {
            bool returnValue = false;
            if (type.Equals(typeof(DateTime)) && value.ToString() != "0001/1/1 0:00:00")
            {
                returnValue = true;
            }
            if (type.Equals(typeof(string))&&!string.IsNullOrEmpty(value.ToString()))
            {
                returnValue = true;
            }
            if (IsNumeric(value)&&!string.IsNullOrEmpty(value.ToString()))
            {
                returnValue = true;
            }
            return returnValue;
        }
        public static bool IsNumeric(object AObject)
        {
            return AObject is sbyte || AObject is byte ||
                AObject is short || AObject is ushort ||
                AObject is int || AObject is uint ||
                AObject is long || AObject is ulong ||
                AObject is double ||
                AObject is decimal || AObject is float ||
                AObject is double;
        }
        public static string FormartValue(SqlConditionEnum cond,Type fieldType,object value)
        {
            string str = "";
            if (fieldType.Equals(typeof(DateTime)))
            {
                str = "'"+value.ToString()+"'";
            }
            else if (fieldType.Equals(typeof(string))&&cond.Equals(SqlConditionEnum.Like))
            {
                str = "'%"+value.ToString()+"%'";
            }
            else if(fieldType.Equals(typeof(string)))
            {
                str = "'" + value.ToString() + "'";
            }            
            else
            {
                str = value.ToString();
            }
            return str;
        }
        #endregion
        #region Enum扩展方法
        public static T GetAttribute<T>(this System.Enum value) where T : Attribute
        {
            FieldInfo field = value.GetType().GetField(value.ToString());
            return Attribute.GetCustomAttribute(field, typeof(T)) as T;
        }
        public static int GetValue(this System.Enum value)
        {
            FieldInfo field = value.GetType().GetField(value.ToString());
            return (int)field.GetValue(null);
        }
        public static List<object> GetEnumList(this System.Enum em)
        {
            List<object> data = new List<object>();
            foreach(int enumValue in System.Enum.GetValues(em.GetType()))
            {
                var name = System.Enum.GetName(em.GetType(), enumValue);
                FieldInfo fd = em.GetType().GetField(name);
                object[] attrs = fd.GetCustomAttributes(typeof(RemarkAttribute), false);
                if (attrs.Length > 0)
                {
                    data.Add(new { Value = enumValue, Name = RemarkAttribute.GetEnumRemark(em.GetType(), enumValue) });
                }
                
            }
            return data;
        }
        #endregion

    }
    #region 自定义属性
    [System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    public class RemarkAttribute : Attribute
    {
        private string m_remark;
        public RemarkAttribute(string remark)
        {
            this.m_remark = remark;
        }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark
        {
            get { return m_remark; }
            set { m_remark = value; }
        }
        /// <summary>
        /// 获取枚举的备注信息
        /// </summary>
        /// <param name="val">枚举值</param>
        /// <returns></returns>
        public static string GetEnumRemark(Type type, int val)
        {
            var name = System.Enum.GetName(type, val);
            FieldInfo fd = type.GetField(name);
            if (fd == null)
                return string.Empty;
            object[] attrs = fd.GetCustomAttributes(typeof(RemarkAttribute), false);
            string remark = string.Empty;
            foreach (RemarkAttribute attr in attrs)
            {
                remark = attr.Remark;
            }
            return remark;
        }
        /// <summary>
        /// 将枚举转换为CaseWhen语句
        /// </summary>
        /// <param name="enumType">枚举的类型</param>
        /// <param name="changeMethod">将枚举的值转换成名称的方法</param>
        /// <returns></returns>
        public static string EnumToCaseWhen(Type type)
        {
            StringBuilder caseSqlStr = new StringBuilder();
            foreach (int enumValue in System.Enum.GetValues(type))
            {
                caseSqlStr.AppendFormat(" WHEN {0} THEN '{1}'", enumValue, GetEnumRemark(type, enumValue));
            }
            return caseSqlStr.ToString();
        }

    }
    #endregion
}
